import os, sys
from subprocess import Popen, PIPE, STDOUT

#Class that represents a pyOODSM job
class Job:

    #Constructor. A file, containing a list of available hosts
    #is required, along with a accesmethod fx "ssh".
    def __init__(self, hostfile, access_cmd):
        self.access_cmd = access_cmd
        self.hosts = []
        self.processes = []
        self.lasthost = 0
        self.path = sys.path[0]
        self.job = ""
        if os.path.isfile(hostfile):
            fp = open(hostfile, 'r')
            lines = fp.readlines()
            self.hosts = map(str.strip, lines)


        if len(self.hosts) == 0:
            self.hosts.append("")


    
    #Function for setting up the job parameters. These are the path to the masterlog,
    #the masters loglevel, where the results from the master and pyro nameserver sould be
    #sent to.
    def setup(self, masterlog, loglevel, masterpipe, nameserverpipe):
        self.masterlog = masterlog
        self.loglevel = loglevel
        self.masterpipe = masterpipe
        self.nameserverpipe = nameserverpipe

        masterargs = self.loglevel + " " + self.masterlog
        self.master = self.spawn("DSMmaster.py", masterargs, self.masterpipe, self.access_cmd, self.hosts[0])

        self.nameserver = self.spawn_clean("pyro-ns", "", self.nameserverpipe, self.access_cmd, self.hosts[0])

        

        
    #Function for bulding the job, ie making the job ready to be runned.
    def make_job(self):
        self.job = self.job + self.nameserver + " & "
        self.job = self.job + "sleep 10;"
        self.job = self.job + self.master + " & "
        self.job = self.job + "sleep 10;"
        
        for p in self.processes:
            self.job = self.job + p + " & "

        self.job = self.job.rpartition(' & ')[0]
        self.job = self.job + "; sleep 10;"
        self.job = self.job + self.shutdown()
        self.job = self.job + "; sleep 10"


    #Function for adding processes to the job. All that is required is
    #the name of the file to be runned, arhuments for the process and a
    #filename to pipe the results to.
    def add_process(self,filename, args, stdout):
        hostnr = (self.lasthost + 1) % len(self.hosts)-1
        self.lasthost = self.lasthost + 1
        proc = self.spawn(filename, args, stdout, self.access_cmd, self.hosts[hostnr])
        self.processes.append(proc)
        

    #Internal function for creating a new process. That is building the
    #string to be executed as part of the shellscript.
    def spawn(self, filename, args, stdout, access, host):
        if host == "":
            if stdout == "stdout":
                cmd = "python " + self.path + "/" + filename + " " + args
            else:
                cmd = "python " + self.path + "/" + filename + " " + args + " > " + stdout
        else:
            if stdout == "stdout":
                cmd = access + " " + host + " \"python " + self.path + "/" + filename + " " + args + "\""
            else:
                cmd = access + " " + host + " \"python " + self.path + "/" + filename + " " + args + " > " + stdout + "\""
        return cmd


    #Same as spawn(), but this is used to start processes, that is not
    #python processes.
    def spawn_clean(self, filename, args, stdout, access, host):
        if host == "":
            if stdout == "stdout":
                cmd = filename + " " + args
            else:
                cmd =  filename + " " + args + " > " + stdout
        else:
            if stdout == "stdout":
                cmd = access + " " + host + " \"" + filename + " " + args + "\""
            else:
                cmd = access + " " + host + " \"" + filename + " " + args + " > " + stdout + "\""
        return cmd
    

    #Simply runnes the job.
    def run(self):
        p = Popen([self.job], stdin=PIPE, stdout=None, stderr=None, shell=True)
        p.wait()
    

    #Function for creating the shutdown pocesses. 
    def shutdown(self):
        return self.spawn_clean("pyro-nsc shutdown", "", "stdout", self.access_cmd, self.hosts[0])


    







